<template>
  <div class="video_upload">
    <el-upload
      class="upload-demo"
      drag
      action="#"
      :http-request="startUpload"
      :file-list="fileList"
      v-if="fileList.length < 1"
    >
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">
        将文件拖到此处，或
        <em>点击上传</em>
      </div>
    </el-upload>
    <div
      class="file_list_info"
      style="height: 50px; width: 510px"
      v-if="fileList.length > 0"
    >
      <div
        class="file_info"
        v-for="file in fileList"
        :key="file.uid"
        style="width: 100%; height: 100%"
      >
        <div style="width: 450px; height: 50px; font-size: 1px">
          <div style="height: 40px">
            <div class="info_left" style="float: left">
              <span>{{ file.name }}</span>
            </div>
            <div class="info_top" style="width: 140px; float: right">
              <span
                class="button"
                v-if="file.status === '1'"
                @click="stopUplaod(file)"
                >暂停</span
              >
              <span
                class="button"
                v-if="file.status === '2'"
                @click="reUpload(file)"
                >开始</span
              >
              <span
                class="button"
                v-if="file.status === '3'"
                @click="reUpload(file)"
                >重试</span
              >
              <span class="button">删除</span>
              <span>{{ file.percentage }}%</span>
            </div>
          </div>
          <div class="buttom" style="width: 100%">
            <div v-if="file.status !== '1'" style="width: 100%">
              <span>{{ getFileStatusMsg(file.status) }}</span>
            </div>
            <div v-if="file.status === '1'" style="width: 100%">
              <span
                >已上传: {{ formatFileSize(file.totalLoaded) }}/{{
                  formatFileSize(file.size)
                }}</span
              >
              <span>上传速度: {{ file.speed }}</span>
              <span>剩余时间: {{ file.estimateTime }}</span>
            </div>
            <el-progress
              :show-text="false"
              :percentage="file.percentage"
            ></el-progress>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { fragmentUploadUrls } from "@/api/file";
import axios from "axios";

export default {
  data() {
    return {
      imgUploadUrl:
        process.env.VUE_APP_BASE_API + '/file/upload',
      status: "0", // 0上传完成 1上传中 2暂停 3错误 4等待上传
      fileList: [],
    };
  },
  methods: {
    getFileStatusMsg(status) {
      let msg = "";
      switch (status) {
        case "0":
          msg = "上传完成";
          break;
        case "2":
          msg = "暂停中";
          break;
        case "3":
          msg = "上传出错";
          break;
        case "4":
          msg = "等待上传";
          break;
      }
      return msg;
    },

    // 时间戳格式化
    formatSeconds(value) {
      let result = parseInt(value);
      let h =
        Math.floor(result / 3600) < 10
          ? "0" + Math.floor(result / 3600)
          : Math.floor(result / 3600);
      let m =
        Math.floor((result / 60) % 60) < 10
          ? "0" + Math.floor((result / 60) % 60)
          : Math.floor((result / 60) % 60);
      let s =
        Math.floor(result % 60) < 10
          ? "0" + Math.floor(result % 60)
          : Math.floor(result % 60);

      let res = "";
      if (h !== "00") res += `${h}h`;
      if (m !== "00") res += `${m}min`;
      res += `${s}s`;
      return res;
    },

    // 大小格式化
    formatFileSize(size) {
      var s = 0;
      s = size / (1024 * 1024 * 1024);
      if (s >= 1) {
        return Math.round(s) + "GB";
      }
      s = s * 1024;
      if (s >= 1) {
        return Math.round(s) + "MB";
      }
      s = s * 1024;
      return Math.round(s) + "kB";
    },

    // 获取上传信息（当前速度，剩余时间，已上传大小，进度）
    getUploadInfo(file, e) {
      let totalLoaded =
        (file.totalLoaded | 0) + e.loaded - (file.topLoaded | 0);
      file.totalLoaded = totalLoaded;
      let uoploadTime = Math.ceil(
        (e.timeStamp - (file.topTimeStamp | 0)) / 1000
      ); //上传时间
      let uoploadSize = Math.ceil(e.loaded - (file.topLoaded | 0)); //上传文件大小
      let speed = Math.ceil(uoploadSize / uoploadTime / 1024) + "KB/S"; //上传速度
      let estimateTime = Math.ceil(
        ((file.size - file.totalLoaded) / uoploadSize) * uoploadTime
      ); //剩余所需时间
      let percentage = Math.ceil(
        ((e.loaded / e.total + file.successIndex.length) * 100) /
          file.totalIndex.length
      ); //百分比进度
      file.percentage = percentage;
      file.speed = speed;
      file.estimateTime = this.formatSeconds(estimateTime);
      file.topLoaded = e.loaded;
      file.topTimeStamp = e.timeStamp;
      if (file.status === "4") {
        file.status = "1";
      }
      if (file.status === "1") {
        this.changeFileList();
      }
    },

    // 重新赋值 渲染页面
    changeFileList(file) {
      if (file && file.status && file.status === "2") {
        return;
      }
      let newFileList = [];
      this.fileList.forEach((item) => {
        newFileList.push(item);
      });
      this.fileList = newFileList;
    },

    // 上传接口返回错误
    httpError(file, index) {
      file.status = "3";
      file.errorIndex.push(index);
      this.changeFileList(file);
    },

    uplaodSuccess(params) {
      this.$emit("success", params);
    },
    // 上传接口返回成功
    httpSuccess(file, i, shardIndex) {
      file.endTime = new Date().getTime();
      file.uploadTime = (file.endTime - file.startTime) / 1000; //分片上传时间 单位秒
      file.successIndex.push(shardIndex[i]);
      // 判断所有切片都上传成功
      if (file.successIndex.length === file.totalIndex.length) {
        file.status = "0";
        const params = { objectName: file.objectName, contentType: file.type, bucketName:  file.bucketName};
        this.uplaodSuccess(params);
      }
      // 修改fileList
      this.changeFileList(file);
      i++;
      if (file.status === "1") {
        this.httpUpload(file, i, shardIndex);
      }
    },

    // 重新上传
    reUpload(file) {
      if (file.status !== "4" && file.status !== "1") {
        file.status = "4";
        this.changeFileList(file);
      }
      if (
        file.doingIndex.length !==
        file.errorIndex.length + file.successIndex.length
      ) {
        setTimeout(() => {
          this.reUpload(file);
        }, 3000);
        return;
      }
      // 需要上传的分片
      let shardIndex = [];
      file.successIndex.forEach((item) => {
        item.end - item.start;
      });
      file.totalIndex.forEach((element) => {
        if (file.successIndex.indexOf(element) < 0) {
          shardIndex.push(element);
        }
      });
      this.httpUpload(file, 0, shardIndex);
      return true;
    },

    // 暂停上传
    stopUplaod(file) {
      file.status = "2";
      let newFileList = [];
      this.fileList.forEach((item) => {
        newFileList.push(item);
      });
      this.fileList = newFileList;
    },

    // 调用后台接口上传
    httpUpload(file, i, shardIndex) {
      // 获取切片文件
      const index = shardIndex[i];
      if (!index) {
        return;
      }
      file.start = index.start;
      file.end = index.end;
      const shardFile = file.slice(file.start, file.end);
      // 请求参数
      file.topLoaded = 0;
      file.topTimeStamp = 0;
      file.doingIndex.push(shardIndex);
      axios
        .put(index.url, shardFile, {
          //添加请求头
          headers: { "Content-Type": "binary" },
          onUploadProgress: (e) => {
            this.getUploadInfo(file, e);
          },
        })
        .then(() => {
          this.httpSuccess(file, i, shardIndex);
        }).catch(()=>{
          this.httpError(file,shardIndex)
        });
    },

    // 新增文件首次上传
    startUpload(param) {
      const file = param.file;
      this.fileList.push(file);
      file.successIndex = []; //已成功上传的分片
      file.errorIndex = []; //上传失败的分片
      file.doingIndex = []; //执行过上传的分片
      file.status = "4";
      file.percentage = 0;
      // 需要上传的分
      let data = new FormData();
      data.append("file", file);
      fragmentUploadUrls(data)
        .then((v) => {
          file.totalIndex = v.data.urls; //所有分片
          file.status = "1";
          file.objectName = v.data.objectName;
          file.bucketName = v.data.bucketName;
          this.httpUpload(file, 0, v.data.urls);
        })
        .catch(() => {
          this.fileList = [];
        });
    },
  },
};
</script>



<style lang="scss" scoped>
.video_upload {
  padding: 10px 0;
  .buttom {
    span {
      margin-right: 20px;
    }
  }
  .info_top {
    span {
      margin-left: 20px;
    }
    .button {
      visibility: hidden;
      cursor: pointer;
    }
  }
  .info_top :hover {
    color: chocolate;
  }

  .file_list_info :hover {
    .info_top {
      .button {
        visibility: visible;
      }
    }
  }
}
</style>